package net.zdsoft.wpchat.support.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import net.zdsoft.keel.cache.Cache;
import net.zdsoft.keel.cache.CacheObject;
import net.zdsoft.keel.cache.KeyMaker;
import net.zdsoft.keel.util.ArrayUtils;
import net.zdsoft.wpchat.support.dao.AuthDao;
import net.zdsoft.wpchat.support.entity.AuthCatalog;
import net.zdsoft.wpchat.support.entity.AuthConfig;
import net.zdsoft.wpchat.support.entity.AuthModule;
import net.zdsoft.wpchat.support.entity.AuthOperation;
import net.zdsoft.wpchat.support.entity.GroupPermission;
import net.zdsoft.wpchat.support.entity.UserCatalog;
import net.zdsoft.wpchat.support.entity.UserConfig;
import net.zdsoft.wpchat.support.entity.UserModule;
import net.zdsoft.wpchat.support.entity.UserOperation;
import net.zdsoft.wpchat.support.enums.PermissionTypeEnum;
import net.zdsoft.wpchat.support.service.AuthCacheService;

/**
 * 权限缓存Service
 * 
 * @author xuan
 * @version $Revision: 1.0 $, $Date: 2014-9-22 下午10:44:04 $
 */
@Service
public class AuthCacheServiceImpl implements AuthCacheService {
    private static final String SYSTEM_CATALOG_KEY = "system.catalog";
    private static final String SYSTEM_MODULE_KEY = "system.module";
    private static final String SYSTEM_OPERATION_KEY = "system.operation";
    private static final String USER_CONFIG_KEY = "user.config";

    private static final Logger log = LoggerFactory.getLogger(AuthCacheServiceImpl.class);
    @Resource
    private AuthDao authDao;
    @Resource
    private Cache<String, Object> cache;

    @Override
    public void refreshPermission() {
        ((CacheObject) cache.get(SYSTEM_CATALOG_KEY)).setValue(null);
        ((CacheObject) cache.get(SYSTEM_MODULE_KEY)).setValue(null);
        ((CacheObject) cache.get(SYSTEM_OPERATION_KEY)).setValue(null);
        ((CacheObject) cache.get(USER_CONFIG_KEY)).setValue(null);
    }

    @Override
    public UserConfig getUserConfigByGroupIds(String[] groupIds) {
        // 实际上保存的是组的权限
        CacheObject userConfigMapCache = (CacheObject) cache.get(USER_CONFIG_KEY);
        if (userConfigMapCache.isExpired()) {
            userConfigMapCache.setValue(new HashMap<String, UserConfig>());
        }

        Map<String, UserConfig> map = (Map<String, UserConfig>) userConfigMapCache.getValue();
        String key = KeyMaker.getKey(groupIds);
        UserConfig userConfig = map.get(key);

        if (userConfig == null) {
            userConfig = getUserConfig(groupIds);
            if (log.isDebugEnabled()) {
                log.debug("put UserConfig[" + key + "]");
            }

            map.put(key, userConfig);
        }

        return userConfig;
    }

    @Override
    public Map<String, AuthCatalog> getCatalogMap() {
        CacheObject catalogCache = (CacheObject) cache.get(SYSTEM_CATALOG_KEY);
        if (catalogCache.isExpired()) {
            catalogCache.setValue(authDao.findCatalogMap());
        }
        return (Map<String, AuthCatalog>) catalogCache.getValue();
    }

    @Override
    public Map<String, AuthModule> getModuleMap() {
        CacheObject moduleCache = (CacheObject) cache.get(SYSTEM_MODULE_KEY);
        if (moduleCache.isExpired()) {
            moduleCache.setValue(authDao.findModuleMap(getCatalogMap()));
        }
        return (Map<String, AuthModule>) moduleCache.getValue();
    }

    @Override
    public Map<String, AuthOperation> getOperationMap() {
        CacheObject operationCache = (CacheObject) cache.get(SYSTEM_OPERATION_KEY);
        if (operationCache.isExpired()) {
            operationCache.setValue(authDao.findOperationMap(getModuleMap()));
        }
        return (Map<String, AuthOperation>) operationCache.getValue();
    }

    @Override
    public UserConfig getUserConfig(String[] groupIds) {
        List<GroupPermission> groupPerms = authDao.findGroupPerms(groupIds);
        if (groupPerms == null) {
            groupPerms = new ArrayList<GroupPermission>();
        }
        // 目前只考虑多个组时(当含有all时取all,其他的没有考虑)

        AuthConfig authConfig = new AuthConfig(getCatalogMap(), getModuleMap(), getOperationMap());
        UserConfig userConfig = new UserConfig();
        // 设置用户所属组
        List groupNamelist = authDao.findGroupNames(groupIds);

        userConfig.setRoles(ArrayUtils.toArray(groupNamelist));

        for (int i = 0; i < groupPerms.size(); i++) {
            GroupPermission groupPerm = groupPerms.get(i);
            AuthOperation authOperation = authConfig.getOperation(groupPerm.getAuthOperationId());

            if (authOperation.getModule() == null) {
                log.debug(authOperation.getId() + ";" + authOperation.getName());
            }

            if (authOperation == null) {
                log.error("Invalid operation[" + groupPerm.getAuthOperationId() + "]");
                continue;
            }

            if (!ArrayUtils.contains(authOperation.getScope(), String.valueOf(groupPerm.getPermission()))) {
                log.error("Invalid permission[" + groupPerm.getPermission() + "]");
                continue;
            }
            AuthModule authModule = authConfig.getModule(authOperation.getModule().getId());

            if (authModule == null) {
                log.error("Invalid model[" + authOperation.getModule().getId() + "]");
                continue;
            }

            if (authModule.getCatalog() == null) {
                log.info("Invalid model[" + authOperation.getModule().getId() + "]");
                continue;
            }
            AuthCatalog authCatalog = authConfig.getCatalog(authModule.getCatalog().getId());

            if (authCatalog == null) {
                log.error("Invalid catalog[" + authModule.getCatalog().getId() + "]");
                continue;
            }

            UserCatalog userCatalog = userConfig.putUserCatalog(new UserCatalog(authCatalog));

            UserModule userModule = userCatalog.putUserModule(new UserModule(authModule));

            UserOperation userOperation = userModule.putUserOperation(new UserOperation(authOperation,
                    PermissionTypeEnum.valueOf(groupPerm.getPermission())));

            // 注册operation，使得能够通过action的名字检索到
            userConfig.registerOperation(userOperation);
        }

        // 按照visibleIndex进行排序
        userConfig.orderCatalogByVisibleIndex();
        List userCatalogList = userConfig.getUserCatalogs();

        for (int i = 0; i < userCatalogList.size(); i++) {
            UserCatalog userCatalog = (UserCatalog) userCatalogList.get(i);
            userCatalog.orderModuleByVisibleIndex();
        }
        return userConfig;
    }

}
